﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AcadApp = Autodesk.AutoCAD.Windows;
using Wnd = System.Windows.Forms;
namespace _16与外部文件_txt_交互
{
    public class Class1
    {
        public struct BlockData
        {
            public string blockName;
            public string layerName;
            public string X;
            public string Y;
            public string Z;
            public string ZS;
            public string XS;
        }

        public struct TxtData
        {
            public string blockName;
            public string layerName;
            public Point3d position;
            public Dictionary<string, string> attrs ;
        }

        [CommandMethod("DataToTxtDemo")]
        public void DataToTxtDemo()
        {
            Database db = HostApplicationServices.WorkingDatabase;

            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            TypedValue[] values = new TypedValue[]
            {
                new TypedValue((int)DxfCode.Start,"INSERT"),
                new TypedValue((int)DxfCode.LayerName,"ssd")
            };
            SelectionFilter filter = new SelectionFilter(values);
            PromptSelectionResult psr = ed.GetSelection(filter);
            if (psr.Status == PromptStatus.OK)
            {
                ObjectId[] ids = psr.Value.GetObjectIds();
                BlockData[] data = this.GetBlockRefData(db, ids);

                Wnd.SaveFileDialog saveDlg = new Wnd.SaveFileDialog();
                saveDlg.Title = "保存图形数据";
                saveDlg.Filter = "文本文件(*.txt)|*.txt";
                saveDlg.InitialDirectory = Path.GetDirectoryName(db.Filename);
                string fileName = Path.GetFileName(db.Filename);
                saveDlg.FileName = fileName.Substring(0, fileName.IndexOf('.'));
                Wnd.DialogResult saveDlgRes = saveDlg.ShowDialog();
                if (saveDlgRes == Wnd.DialogResult.OK)
                {
                    string[] contents = new string[data.Length];
                    for (int i = 0; i < data.Length; i++)
                    {
                        contents[i] = data[i].blockName + "," + data[i].layerName + "," + data[i].X + "," + data[i].Y + "," + data[i].Z + "," + data[i].ZS + "," + data[i].XS;
                    }
                    File.WriteAllLines(saveDlg.FileName, contents);
                }
            }
        }

        [CommandMethod("DataToCadDemo")]
        public void DataToCadDemo()
        {
            Database db = HostApplicationServices.WorkingDatabase;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            Wnd.OpenFileDialog openDlg = new Wnd.OpenFileDialog();
            openDlg.Title = "打开数据文件";
            openDlg.Filter = "文本文件(*.txt)|*.txt";
            Wnd.DialogResult openRes  = openDlg.ShowDialog();
            if (openRes == Wnd.DialogResult.OK)
            {
               string[] contents =  File.ReadAllLines(openDlg.FileName);
               List<TxtData> datas;
                int row = this.TransData(contents, out datas);
               if (row < 0)
               {
                   this.InsertAttrBlockReference(db, datas);
               }
               else
               {
                   ed.WriteMessage("外部数据文件在第{0}出错",row+1);
               }
            }
        }

        [CommandMethod("DeleteBlockDemo")]
        public void DeleteBlockDemo()
        {
            Database db = HostApplicationServices.WorkingDatabase;

            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            TypedValue[] values = new TypedValue[]
            {
                new TypedValue((int)DxfCode.Start,"INSERT"),
                new TypedValue((int)DxfCode.LayerName,"ssd")
            };
            SelectionFilter filter = new SelectionFilter(values);
            PromptSelectionResult psr = ed.GetSelection(filter);
            if (psr.Status == PromptStatus.OK)
            {
                ObjectId[] ids = psr.Value.GetObjectIds();
                using (Transaction trans = db.TransactionManager.StartTransaction())
                {
                    for (int i = 0; i < ids.Length; i++)
                    {
                        DBObject obj = ids[i].GetObject(OpenMode.ForWrite);
                        obj.Erase();
                    }
                    trans.Commit();
                }
            }
        }
        /// <summary>
        /// 将数据转换为图形加入模型空间
        /// </summary>
        /// <param name="db"></param>
        /// <param name="data"></param>
        private void InsertAttrBlockReference(Database db, List<TxtData> data)
        {
           
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                for (int i = 0; i < data.Count; i++)
                {
                   
                    if (bt.Has(data[i].blockName))
                    {
                        //获取块的ObjectId
                        ObjectId blockId =bt[data[i].blockName];
                        //声明块参照
                        BlockReference br = new BlockReference(data[i].position,blockId);
                        
                        btr.AppendEntity(br);
                        //添加属性定义
                        BlockTableRecord blockRecord = (BlockTableRecord)blockId.GetObject(OpenMode.ForRead);
                        
                        if (blockRecord.HasAttributeDefinitions)
                        {
                            foreach (ObjectId item in blockRecord)
                            {
                                DBObject obj = item.GetObject(OpenMode.ForRead);
                                if (obj is AttributeDefinition)
                                {
                                    //声明属性参照
                                    AttributeReference attrRef = new AttributeReference();
                                    attrRef.SetAttributeFromBlock((AttributeDefinition)obj, br.BlockTransform);
                                    if (data[i].attrs.ContainsKey(attrRef.Tag.ToString()))
                                    {
                                        attrRef.TextString = data[i].attrs[attrRef.Tag.ToString()];
                                    }
                                    br.AttributeCollection.AppendAttribute(attrRef);
                                    trans.AddNewlyCreatedDBObject(attrRef, true);
                                }
                            }
                        }

                        trans.AddNewlyCreatedDBObject(br, true);
                    }
                }
               
                trans.Commit();
            }

            
        }

        /// <summary>
        /// 整理文件的数据
        /// </summary>
        /// <param name="contents"></param>
        /// <param name="datas"></param>
        /// <returns></returns>
        private int TransData(string[] contents,out List<TxtData> datas)
        {
            datas = new List<TxtData>();
            int row = -1;
            TxtData data = new TxtData();
            for (int i = 0; i < contents.Length; i++)
            {
                string[] con = contents[i].Split(new char[] { ',' });
                data.blockName =con[0];
                data.layerName = con[1];
                double X;
                double Y;
                double Z;
                if (!Double.TryParse(con[2], out X))
                {
                    row = i;
                    break;
                }
                if (!Double.TryParse(con[3], out Y))
                {
                    row = i;
                    break;
                }
                if (!Double.TryParse(con[4], out Z))
                {
                    row = i;
                    break;
                }
                data.position = new Point3d(X,Y,Z);
                data.attrs = new Dictionary<string, string>();
                data.attrs.Add("ZS", con[5].ToString());
                data.attrs.Add("XS", con[6].ToString());
                datas.Add(data);
            }


            return row;
        }

        /// <summary>
        /// 获取块参照的信息
        /// </summary>
        /// <param name="db"></param>
        /// <param name="ids"></param>
        /// <returns></returns>
        private BlockData[] GetBlockRefData(Database db, ObjectId[] ids)
        {
            BlockData[] data = new BlockData[ids.Length];
            using (Transaction trasn = db.TransactionManager.StartTransaction())
            {
                for (int i = 0; i < ids.Length; i++)
                {
                    // 块名  图层  X  Y  Z  ZS  XS 
                    BlockReference br = (BlockReference)ids[i].GetObject(OpenMode.ForRead);
                    data[i].blockName = br.Name;
                    data[i].layerName = br.Layer;
                    data[i].X = br.Position.X.ToString();
                    data[i].Y = br.Position.Y.ToString();
                    data[i].Z = br.Position.Z.ToString();
                    foreach (ObjectId item in br.AttributeCollection)
                    {
                        AttributeReference attRef = (AttributeReference)item.GetObject(OpenMode.ForRead);
                        if (attRef.Tag.ToString() == "ZS")
                        {
                            data[i].ZS = attRef.TextString;
                        }
                        else if (attRef.Tag.ToString() == "XS")
                        {
                            data[i].XS = attRef.TextString;
                        }
                    }
                }
            }
            return data;
        }

    }
}
